﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;

using YouHP.Model;
using YouHP.DALFactory;
using YouHP.Utility;
using YouHP.SqlServerDAL;

namespace YouHP.BLL
{
    public class PrescriptionBLL
    {
        #region 单件模式
        static PrescriptionBLL _Instance;

        public static PrescriptionBLL Instance
        {
            get
            {
                if (_Instance == null)
                {
                    _Instance = new PrescriptionBLL();
                }
                return _Instance;
            }
        }
        #endregion

        #region 药方的查询、添加、更新和删除

        public PrescriptionInfo GetPrescriptionInfo(int pid)
        {
            PrescriptionInfo info = DataAccess.PrescriptionDAL.GetPrescriptionInfo(pid);
            DoctorInfo doctorInfo = DoctorBLL.Instance.GetDoctorInfo(info.DoctorId);
            info.DoctorName = doctorInfo.Name;
            info.DoctorHospital = doctorInfo.Hospital;

            return info;
        }

        public int AddPrescriptionInfo(PrescriptionInfo info)
        {
            return DataAccess.PrescriptionDAL.AddPrescription(info);
        }

        public bool UpdatePrescriptionInfo(PrescriptionInfo info)
        {
            return DataAccess.PrescriptionDAL.UpdatePrescription(info);
        }

        public bool DeletePrescriptionInfo(int pid)
        {
            return DataAccess.PrescriptionDAL.DeletePrescription(pid);
        }

        #endregion

        #region 药方列表及其搜索

        public List<PrescriptionInfo> GetPrescriptionList(int pageSize, int pageIndex, string condStr, out int count)
        {
            List<PrescriptionInfo> list = DataAccess.PrescriptionDAL.GetPrescriptionList(pageSize, pageIndex, condStr, out count);
            for (int idx = 0; idx < list.Count; idx++)
            {
                int doctorId = list[idx].DoctorId;
                if (doctorId < 0)
                    continue;
                DoctorInfo doctorInfo = DoctorBLL.Instance.GetDoctorInfo(list[idx].DoctorId);
                list[idx].DoctorName = doctorInfo.Name;
                list[idx].DoctorHospital = doctorInfo.Hospital;
            }

            return list;
        }

        public List<PrescriptionInfo> GetPrescriptionList(int pageSize, int pageIndex, string condStr, string orderStr, out int count)
        {
            List<PrescriptionInfo> list = DataAccess.PrescriptionDAL.GetPrescriptionList(pageSize, pageIndex, condStr, orderStr, out count);
            for (int idx = 0; idx < list.Count; idx++)
            {
                int doctorId = list[idx].DoctorId;
                if (doctorId < 0)
                    continue;
                DoctorInfo doctorInfo = DoctorBLL.Instance.GetDoctorInfo(list[idx].DoctorId);
                list[idx].DoctorName = doctorInfo.Name;
                list[idx].DoctorHospital = doctorInfo.Hospital;
            }

            return list;
        }

        // We want the doctor name and the hosiptal name be contained in the PrescriptionInfo,
        // there are two ways to implement this, one is modify the stored procedure, and the other
        // is after getting the PrescriptionInfo, get the doctor info separately, 
        // I choose the latter method here, which may hurt the performance but makes life easier.
        public List<PrescriptionInfo> GetPrescriptionList(string condStr)
        {
            List<PrescriptionInfo>  list = DataAccess.PrescriptionDAL.GetPrescriptionList(condStr);
            for (int idx = 0; idx < list.Count; idx++)
            {
                int doctorId = list[idx].DoctorId;
                if (doctorId < 0)
                    continue;
                DoctorInfo doctorInfo = DoctorBLL.Instance.GetDoctorInfo(list[idx].DoctorId);
                list[idx].DoctorName = doctorInfo.Name;
                list[idx].DoctorHospital = doctorInfo.Hospital;
            }

            return list;
        }

        public List<PrescriptionInfo> GetDoctorPrescriptionList(int did)
        {
            string condStr = string.Format("[Prescription].[DoctorId] = {0} AND [Prescription].[ParentId]=0", did);
            return GetPrescriptionList(condStr);
        }

        public List<PrescriptionInfo> GetPrescriptionListByDiseaseId(int diseaseId)
        {
            string condStr = string.Format("[Prescription].[DiseaseId]={0} AND [Prescription].[ParentId]=0", diseaseId);
            int pageSize = 100;
            int pageIndex = 1;
            int count = 0;
            return GetPrescriptionList(pageSize, pageIndex, condStr, out count);
        }

        // Need paging support soon!!!
        public List<PrescriptionInfo> GetClassicPrescriptionListByDiseaseId(int diseaseId)
        {
            string condStr = string.Format("[Prescription].[DiseaseId]={0} AND [Prescription].[IsClassic]=1 AND [Prescription].[ParentId]=0", diseaseId);
            int pageSize = 100;
            int pageIndex = 1;
            int count = 0;
            return GetPrescriptionList(pageSize, pageIndex, condStr, out count);
        }

        #endregion

        public List<DiseasePrescriptionStat> GetDiseasePrescriptionStat(int count)
        {
            return DataAccess.PrescriptionDAL.GetDiseasePrescriptionStat(count);
        }

        public bool UpdateAverageScoreOfPrescription(int pid)
        {
            PrescriptionInfo pInfo = PrescriptionBLL.Instance.GetPrescriptionInfo(pid);
            if (pInfo.Id <= 0)
                return false;

            // If this prescription is a child prescription, skipping update the average score;
            if (pInfo.ParentId != 0)
                return false;

            // Find how many people use this prescription.
            string condStr = string.Format("[Id]={0} OR [ParentId]={0}", pid);
            List<PrescriptionInfo> list = PrescriptionBLL.Instance.GetPrescriptionList(condStr);

            if (list == null || list.Count == 0)
                return false;


            int userCount = list.Count;
            double sumScore = 0.0;
            foreach (PrescriptionInfo pres in list)
            {
                sumScore += pres.Score;
            }

            // New score.
            double newAverageScore = (double) sumScore / userCount;
            newAverageScore = Math.Round(newAverageScore, 2, MidpointRounding.AwayFromZero);
            pInfo.AverageScore = newAverageScore;

            // Update the average score of the prescription.
            return PrescriptionBLL.Instance.UpdatePrescriptionInfo(pInfo);
        }

        public bool UpdateAverageScoreOfAllPrescription()
        {
            string condStr = string.Format(@"[ParentId]=0");
            List<PrescriptionInfo> allPrescriptions = GetPrescriptionList(condStr);
            if (allPrescriptions == null || allPrescriptions.Count == 0)
                return false;

            bool allSucceeded = true;
            foreach (PrescriptionInfo pres in allPrescriptions)
            {
                if (!UpdateAverageScoreOfPrescription(pres.Id))
                {
                    allSucceeded = false;
                    continue;
                }
            }

            return allSucceeded;
        }

        public int AddPrescription(PrescriptionInfo info)
        {
            return DataAccess.PrescriptionDAL.AddPrescription(info);
        }

        public void UpdatePrescriptionsClassicState(int[] idList, bool isClassic)
        {
            for (int idx = 0; idx < idList.Length; idx++)
            {
                int id = idList[idx];

                PrescriptionInfo info = GetPrescriptionInfo(id);

                if (info.IsClassic != isClassic)
                {
                    info.IsClassic = isClassic;
                    UpdatePrescriptionInfo(info);
                }
            }
        }

        public void UpdatePrescriptionsClassicState(int[] idList, bool[] checkList)
        {
            for (int idx = 0; idx < idList.Length; idx++)
            {
                int id = idList[idx];
                bool check = checkList[idx];

                PrescriptionInfo info = GetPrescriptionInfo(id);

                if (info.IsClassic != check)
                {
                    info.IsClassic = check;
                    UpdatePrescriptionInfo(info);
                }
            }
        }
    }
}
